<template>
  <div class="app-container">
    <el-row :gutter="20">
      <!--侧边部门数据-->
      <el-col :xs="9" :sm="6" :md="5" :lg="4" :xl="4">
        <div class="head-container">
          <el-input v-model="deptName" clearable size="small" placeholder="输入部门名称搜索" prefix-icon="el-icon-search" class="filter-item" @input="filterDept" />
        </div>
        <el-tree ref="tree" :data="depts" :props="defaultProps" :expand-on-click-node="false" class="tree-height" node-key="id" highlight-current default-expand-all @node-click="handleNodeClick" />
      </el-col>
      <!--用户数据-->
      <el-col :xs="15" :sm="18" :md="19" :lg="20" :xl="20">
        <!--工具栏-->
        <div class="head-container">
          <div>
            <!-- 搜索 -->
            <el-input v-model="query.name" clearable size="small" placeholder="输入名称或账号搜索" style="width: 200px" class="filter-item" @keyup.enter.native="reloadPage" />
            <el-select v-model="query.status" clearable size="small" placeholder="状态" class="filter-item" style="width: 90px" @change="reloadPage">
              <el-option v-for="(item, index) in dict.userStatus" :key="index" :label="item.name" :value="item.code" />
            </el-select>
            <span>
              <el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="reloadPage">搜索</el-button>
              <el-button class="filter-item" size="mini" type="warning" icon="el-icon-refresh-left" @click="resetReloadPage">重置</el-button>
            </span>
          </div>
          <div class="crud-opts">
            <span class="crud-opts-left">
              <el-button v-permission="permission.add" class="filter-item" size="mini" type="primary" icon="el-icon-plus" @click="toAdd">
                新增
              </el-button>
              <el-button v-permission="permission.edit" class="filter-item" size="mini" type="success" icon="el-icon-edit" :disabled="selections.length !== 1" @click="toEdit(selections[0])">
                修改
              </el-button>
              <el-button slot="reference" v-permission="permission.del" class="filter-item" type="danger" icon="el-icon-delete" size="mini" :disabled="selections.length === 0" @click="toDeleteMy(selections)">
                删除
              </el-button>

              <el-button v-permission="permission.downloadTemplate" class="filter-item" size="mini" type="warning" icon="el-icon-download" @click="doDownloadTemplate">模板下载</el-button>
              <el-upload class="filter-item" v-permission="permission.importExcel" :action="importExcelUrl" :headers="headers" accept=".xls,.xlsx" :on-success="uploadSuccess" :show-file-list="false">
                <el-button icon="el-icon-upload2" size="mini" type="primary">EXCEL导入</el-button>
              </el-upload>
            </span>
          </div>
        </div>
        <!--表单渲染-->
        <el-dialog append-to-body :close-on-click-modal="false" :visible.sync="addShow" :title="myTitle" width="570px">
          <el-form ref="form" :inline="true" :model="myForm" :rules="rules" size="small" label-width="66px">
            <el-form-item label="用户名" prop="name">
              <el-input v-model="myForm.name" />
            </el-form-item>
            <el-form-item label="账号" prop="account">
              <el-input v-model="myForm.account" />
            </el-form-item>
            <el-form-item label="电话" prop="phone">
              <el-input v-model.number="myForm.phone" />
            </el-form-item>
            <el-form-item label="身份证" prop="idCard">
              <el-input v-model="myForm.idCard" />
            </el-form-item>
            <el-form-item label="邮箱" prop="email">
              <el-input v-model="myForm.email" />
            </el-form-item>
            <el-form-item label="部门" prop="deptIds">
              <treeselect v-model="myForm.deptIds" :options="oriDepts" autoDeselectDescendants flat :normalizer="normalizer" style="width: 182px" multiple placeholder="选择部门" />
            </el-form-item>
            <el-form-item label="性别" prop="sex">
              <el-radio-group v-model="myForm.sex" style="width: 178px">
                <el-radio label="1">男</el-radio>
                <el-radio label="0">女</el-radio>
              </el-radio-group>
            </el-form-item>
            <el-form-item label="状态">
              <el-radio-group v-model="myForm.status">
                <el-radio v-for="item in dict.userStatus" :key="item.code" v-model="myForm.status" :label="item.code">{{ item.name }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
            <el-form-item style="margin-bottom: 0" label="角色">
              <treeselect v-model="myForm.roleIds" autoDeselectDescendants flat :options="roles" multiple :normalizer="normalizer1" style="width: 182px" placeholder="选择角色" />
            </el-form-item>
            <el-form-item style="margin-bottom: 0" label="职能">
              <el-select v-model="myForm.ptype" style="width: 182px">
                <el-option v-for="item in dict.position" :key="item.code" :label="item.name" :value="item.code" />
              </el-select>
            </el-form-item>
            <el-form-item label="岗位" prop="job">
              <el-input v-model="myForm.job" />
            </el-form-item>
          </el-form>
          <div slot="footer" class="dialog-footer">
            <el-button type="primary" plain @click="addShow = false">取消</el-button>
            <el-button type="primary" :loading="submitStatus" @click="goSubmit">确认</el-button>
          </div>
        </el-dialog>
        <!--表格渲染-->
        <el-table v-loading="loading" ref="table" :data="tableData" :style="{ width: '100%', height: tableHeight, overflow: 'auto' }" @current-change="handleCurrentChange" @select="selectFuc">
          <el-table-column :selectable="checkboxT" type="selection" width="55" />
          <el-table-column :show-overflow-tooltip="true" prop="name" min-width="80" label="用户姓名" />
          <el-table-column :show-overflow-tooltip="true" prop="account" min-width="120" label="账号" />
          <el-table-column prop="sex" min-width="50" align="center" label="性别">
            <template slot-scope="scope">
              <div v-if="scope.row.sex == '1'">男</div>
              <div v-else>女</div>
            </template>
          </el-table-column>
          <el-table-column :show-overflow-tooltip="true" prop="phone" width="100" label="联系方式" />
          <el-table-column :show-overflow-tooltip="true" prop="deptNames" min-width="230" label="所属单位部门" />
          <el-table-column :show-overflow-tooltip="true" prop="roleNames" min-width="250" label="拥有角色" />
          <el-table-column label="状态" align="center" prop="status">
            <template slot-scope="scope">
              <el-switch v-model="scope.row.status" active-value="1" inactive-value="0" active-color="#409EFF" inactive-color="#F56C6C" @change="changeEnabled(scope.row, scope.row.status)" />
            </template>
          </el-table-column>
          <el-table-column v-if="hasPermission(permission.column)" label="操作" width="215" align="center" fixed="right">
            <template slot-scope="scope">
              <el-button v-permission="permission.edit" size="mini" type="primary" icon="el-icon-edit" @click="toEdit(scope.row)" />

              <el-button v-permission="permission.del" slot="reference" type="danger" icon="el-icon-delete" size="mini" @click="toDeleteMy(scope.row)" />

              <el-button v-permission="permission.edit" type="warning" icon="el-icon-refresh-left" size="mini" @click="changePwd(scope.row)" />
            </template>
          </el-table-column>
        </el-table>
        <!--分页组件-->
        <el-pagination :page-size="page.size" :total="page.total" :current-page="page.page" style="margin-top: 8px" layout="total, prev, pager, next, sizes" @size-change="sizeChangeHandler($event)" @current-change="pageChangeHandler" />
      </el-col>
    </el-row>
  </div>
</template>

<script>
import crudUser from "@/api/system/user";
import { resetPassword } from "@/api/system/user";
import { isvalidPhone } from "@/utils/validate";
import { getTree } from "@/api/system/dept";
import { getAll as getRoles, getRoleByUserId } from "@/api/system/role";
import { mapGetters } from "vuex";
import hasPermission from "@/mixins/hasPermission";
import { download } from "@/api/data";
import { parseTime, downloadFile, downloadTemplateFile } from "@/utils/index";
import { getToken } from "@/utils/auth";

export default {
  name: "User",
  mixins: [hasPermission],
  // 数据字典
  dicts: ["userStatus", "position"],
  data() {
    // 自定义验证
    const validPhone = (rule, value, callback) => {
      if (!value) {
        callback(new Error("请输入电话号码"));
      } else if (!isvalidPhone(value)) {
        callback(new Error("请输入正确的11位手机号码"));
      } else {
        callback();
      }
    };
    return {
      tableHeight: window.innerHeight - 340 + "px",
      loading: true,
      myTitle: "",
      headers: {
        Authorization: getToken(),
      },
      downloadTemplateName: "用户导入模板.xlsx",
      downloadTemplateUrl: "admin/user/downloadTemplate",
      importExcelUrl: "api/admin/user/importExcel",
      myForm: {
        roleIds: ''
      },
      selections: [], //选中的数据
      addShow: false, //用来弹窗显示
      page: {
        size: 10,
        total: 0,
        page: 1,
      },
      query: { name: "", status: "" },
      submitStatus: false,
      tableData: [],
      height: document.documentElement.clientHeight - 180 + "px;",
      deptName: "",
      depts: [],
      oriDepts: [],
      roles: [],
      defaultProps: {
        children: "children",
        label: "name",
        isLeaf: "data.isLeaf",
      },
      permission: {
        add: ["100", "user:add"],
        edit: ["100", "user:edit"],
        del: ["100", "user:del"],
        downloadTemplate: ["100", "user:downloadTemplate"],
        importExcel: ["100", "user:importExcel"],
        column: ["100", "user:add", "user:del", "user:edit"],
      },
      enabledTypeOptions: [
        { key: "1", display_name: "激活" },
        { key: "0", display_name: "锁定" },
      ],
      rules: {
        name: [
          { required: true, message: "请输入用户名", trigger: "blur" },
          {
            min: 2,
            max: 20,
            message: "长度在 2 到 20 个字符",
            trigger: "blur",
          },
        ],
        account: [
          { required: true, message: "请输入账号", trigger: "blur" },
          {
            min: 2,
            max: 20,
            message: "长度在 2 到 32 个字符",
            trigger: "blur",
          },
        ],
        phone: [{ required: true, trigger: "blur", validator: validPhone }],
        deptIds: [{ required: true, message: "请选择部门", trigger: "blur" }],
      },
    };
  },
  computed: {
    ...mapGetters(["user"]),
  },
  mounted() {
    this.loadRoles();
    this.loadDepts();
    this.getData();
  },
  methods: {
    /**
     * 上传成功处理
     */
    uploadSuccess(response) {
      const code = response.code;
      if (code && code !== 200) {
        this.$message({
          message: response.msg,
          type: "error",
        });
      } else {
        this.$message({
          message: "上传成功",
          type: "success",
        });
        this.getData();
      }
    },
    //模板下载
    /**
     * 通用导出模板
     */
    doDownloadTemplate() {
      download(this.downloadTemplateUrl)
        .then((result) => {
          downloadTemplateFile(result, this.downloadTemplateName);
        })
        .catch(() => { });
    },
    //显示弹窗
    toAdd() {
      this.addShow = true;
      this.myTitle = "新增用户";
      this.myForm = {};
      this.$nextTick(() => {
        this.$refs["form"].clearValidate();
      });
    },
    //显示弹窗赋值
    toEdit(data) {
      data.roleIds = data.roleIds ? data.roleIds.filter(item => item !== null && item !== undefined) : []
      this.myForm = data;
      this.myTitle = "编辑用户";
      this.addShow = true;
      this.$nextTick(() => {
        this.$refs["form"].clearValidate();
      });
    },
    // 当前页改变
    pageChangeHandler(e) {
      this.page.page = e;
      this.getData();
    },
    // 每页条数改变
    sizeChangeHandler(e) {
      this.page.size = e;
      this.page.page = 1;
      this.getData();
    },
    //刷新第一页数据
    reloadPage() {
      this.page.page = 1;
      this.selections = []
      this.getData();
    },
    //重置搜索
    resetReloadPage() {

      this.page = {
        size: 10,
        total: 0,
        page: 1,
      };
      this.query = { name: "", status: "" };
      this.getData();
    },

    //刷新列表
    getData() {
      this.query.pageNo = this.page.page - 1;
      this.query.pageSize = this.page.size;
      this.loading = true;
      crudUser.list(this.query).then((res) => {
        if (res.code == 200) {
          this.loading = false;
          this.tableData = res.data.content;
          this.page.total = res.data.totalElements;
        }
      });
    },
    // 提交前做的操作
    goSubmit() {
      this.$refs["form"].validate((valid) => {
        if (valid) {
          this.myForm.deptId = this.myForm.deptIds.join(",");
          this.myForm.roleId = this.myForm.roleIds.join(",");
          if (this.myForm.deptIds && this.myForm.deptIds.length === 0) {
            this.$message({
              message: "部门不能为空",
              type: "error",
            });
            return false;
          }
          if (this.myForm.roleIds && this.myForm.roleIds.length === 0) {
            this.$message({
              message: "角色不能为空",
              type: "error",
            });
            return false;
          }
          this.doSubmit();
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },

    //真正的去提交
    doSubmit() {
      this.submitStatus = true;
      crudUser
        .edit(this.myForm)
        .then((res) => {
          this.submitStatus = false;
          if (res.code == 200) {
            if (this.myForm.hasOwnProperty("id") && this.myForm.id) {
              this.$notify({
                title: "成功",
                message: "更新成功",
                type: "success",
              });
            } else {
              this.$notify({
                title: "成功",
                message: "新增成功，默认密码：Cico@123",
                type: "success",
              });
            }
            //刷新表格
            this.reloadPage();
            this.addShow = false;
          } else {
            this.$notify.error({
              title: "错误",
              message: "更新失败",
            });
          }
        })
        .catch(() => {
          this.submitStatus = false;
          this.$notify.error({
            title: "错误",
            message: "更新失败",
          });
        });
    },

    //点击删除
    toDeleteMy(data) {
      this.$confirm("确认要删除吗？")
        .then((_) => {
          let ids = [];
          if (data instanceof Array) {
            data.forEach((val) => {
              ids.push(val.id);
            });
          } else {
            ids.push(data.id);
          }
          crudUser
            .del(ids)
            .then((res) => {
              if (res.code == 200) {
                this.$notify({
                  title: "成功",
                  message: "删除成功",
                  type: "success",
                });
                this.reloadPage();
              } else {
                this.$notify.error({
                  title: "错误",
                  message: "删除失败",
                });
              }
            })
            .catch(() => {
              this.$notify.error({
                title: "错误",
                message: "删除失败",
              });
            });
        })
        .catch((_) => { });
    },
    //点击复选框
    selectFuc(selection, row) {
      let oldSelect = this.$refs.table.selection;
      if (oldSelect.length === 0) {
        this.$refs.table.toggleRowSelection(row, false);
        this.$refs.tree.setCurrentKey(
          selection.deptIds ? selection.deptIds[0] : ""
        );
        const selected = this.$refs.tree.getCurrentNode();
        // 若当前组件有父节点 展开其所有父类节点
        if (
          this.$refs.tree.getNode(selected) &&
          this.$refs.tree.getNode(selected).parent
        ) {
          this.expandParents(this.$refs.tree.getNode(selected).parent);
        }
      } else {
        this.handleCurrentChange(row, selection[0]);
      }
    },
    // 点击表格行触发单选
    handleCurrentChange(selection, row) {
      if (!selection) {
        return false;
      }
      this.$refs.table.clearSelection(); //清空之前勾选的
      this.$refs.table.toggleRowSelection(row, false); //单选则将之前的选项勾掉
      this.$refs.table.toggleRowSelection(selection, true); //单选则将选项勾上
      this.selections = this.$refs.table.selection;
      this.$refs.tree.setCurrentKey(
        selection.deptIds ? selection.deptIds[0] : ""
      );
      const selected = this.$refs.tree.getCurrentNode();
      // 若当前组件有父节点 展开其所有父类节点
      if (
        this.$refs.tree.getNode(selected) &&
        this.$refs.tree.getNode(selected).parent
      ) {
        this.expandParents(this.$refs.tree.getNode(selected).parent);
      }
    },
    expandParents(node) {
      // 展开所有祖宗节点
      node.expanded = true;
      if (node.parent) {
        this.expandParents(node.parent);
      }
    },
    changePwd(data) {
      this.$confirm("此操作将重置密码, 是否继续？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        resetPassword(data).then(() => {
          this.$message({
            message: "操作成功！默认密码：Cico@123",
            type: "success",
          });
        });
      });
    },
    normalizer(node) {
      if (node.children == null || !node.children.length) {
        delete node.children;
      }
      return {
        id: node.id,
        label: node.name,
        children: node.children,
      };
    },
    normalizer1(node) {
      if (node.children == null || !node.children.length) {
        delete node.children;
      }
      if (!node.data) {
        node.data = {
          code: "",
          name: "请选择",
        };
      }
      return {
        id: node.data.id,
        label: node.data.name,
        children: node.children,
      };
    },
    filterDept() {
      if (this.deptName) {
        const val = [];
        this.filterChildren(this.oriDepts, val);
        this.depts = val;
      } else {
        this.depts = this.oriDepts;
      }
    },
    filterChildren(children, val) {
      children.filter((it) => {
        if (it.name && it.name.indexOf(this.deptName) >= 0) {
          val.push(it);
        }
        if (it.children) {
          this.filterChildren(it.children, val);
        }
      });
    },
    loadDepts(params) {
      getTree(params).then((res) => {
        this.depts = res.data;
        this.oriDepts = JSON.parse(JSON.stringify(res.data));
        // 默认选中第一个节点
        if (this.depts && this.depts.length) {
          const id = this.depts[0].id;
          this.$nextTick(() => {
            this.$refs.tree && this.$refs.tree.setCurrentKey(id);
          });
        }
      });
    },
    // 获取弹窗内角色数据
    loadRoles() {
      getRoles()
        .then((res) => {
          this.roles = res.data;
        })
        .catch(() => { });
    },
    // 切换部门
    handleNodeClick(data) {
      try {
        if (data.pid === "0") {
          this.query.deptId = data.id;
        } else {
          this.query.deptId = data.id;
        }
        this.reloadPage();
      } catch (e) {
        console.log(e)
      }

    },
    // 改变状态
    changeEnabled(data, val) {
      this.$confirm(
        '此操作将 "' +
        this.dict.label.userStatus[val] +
        '" ' +
        data.name +
        ", 是否继续？",
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }
      )
        .then(() => {
          crudUser
            .enable(data)
            .then((res) => {
              this.$notify({
                title: this.dict.label.userStatus[val] + "成功",
                type: "success",
                duration: 2500,
              });
            })
            .catch(() => {
              this.$notify({
                title: this.dict.label.userStatus[val] + "失败",
                type: "error",
                duration: 2500,
              });
            });
        })
        .catch(() => {
          if (val === "1") {
            data.status = "0";
          } else {
            data.status = "1";
          }
        });
    },
    checkboxT(row, rowIndex) {
      return row.id !== this.user.id;
    },
  },
};
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
::v-deep .vue-treeselect__control,
::v-deep .vue-treeselect__placeholder,
::v-deep .vue-treeselect__single-value {
  height: 30px;
  line-height: 30px;
}

.user-page {
  .tree-height {
    max-height: calc(100vh - 235px);
    overflow-y: auto;
  }
}
::v-deep .el-dialog {
  overflow: visible;
}
</style>
<style>
.crud-opts {
  padding: 4px 0;
  display: -webkit-flex;
  display: flex;
  align-items: center;
}

.crud-opts .crud-opts-right {
  margin-left: auto;
}
</style>
